/**
 *
 * <p>Title: HeroPlaytimeRecord.java</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2004 Sun Microsystems, Inc.</p>
 * <p>Company: Sun Microsystems, Inc</p>
 * @author Jeff Kesselman
 * @version 1.0
 */
package com.worldwizards;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import com.hero.Hero;
import com.hero.objects.characteristics.Characteristic;
import com.hero.util.Constants;

/**
 *
 * <p>Title: HeroPlaytimeRecord.java</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2004 Sun Microsystems, Inc.</p>
 * <p>Company: Sun Microsystems, Inc</p>
 * @author Jeff Kesselman
 * @version 1.0
 */
public class HeroPlaytimeRecord implements Comparable{
	List<HeroPlaytimeRecordListener> listeners = 
		new ArrayList<HeroPlaytimeRecordListener>(); 
    String name;
    private int primaryBody;
    private int primaryStun;
    private int primarySpeed;
    private int primaryDexterity;
    private int primaryConstitution;
    private int primaryRecovery;
    private int primaryEgo;
    private int secondaryBody;
    private int secondaryStun;
    private int secondarySpeed;
    private int secondaryDexterity;
    private int secondaryConstitution;
    private int secondaryRecovery;
    private int secondaryEgo;
    private int bodyTaken;
    private int stunTaken;
    int currentSpeed; // for drains
    int currentDexterity;
    private boolean useSecondaryDEX = false;
    private boolean useSecondarySPD = false;
    private boolean useSecondaryEGO = false;
    private boolean useSecondaryBody = false;
    private boolean useSecondaryStun = false;
    private boolean useSecondaryREC = false;
    private boolean heldAction=false;
    private boolean stunned=false;
    private boolean damagedThisPhase = false;
    private boolean actedThisPhase = false;
	private boolean egoBased = false;
	
    static private int[][] speedChart =
        {{},
         {12},
         {6,12},
         {4,8,12},
         {3,6,9,12},
         {3,5,8,9,12},
         {2,4,6,8,10,12},
         {2,4,6,7,8,10,12},
         {2,3,5,6,8,9,10,12},
         {2,3,4,6,7,8,10,11,12},
         {2,3,4,5,6,8,9,10,11,12},
         {2,3,4,5,6,7,8,9,10,11,12},
         {1,2,3,4,5,6,7,8,9,10,11,12}};
       
    
    /**
     * @param hero
     */
    public HeroPlaytimeRecord(Hero hero) {
        this(hero.getCharacterName(),
                Math.round((float)hero.getCharacteristic(Constants.BODY).getCharacteristicValue()),
                Math.round((float)hero.getCharacteristic(Constants.STUN).getCharacteristicValue()),
                Math.round((float)hero.getCharacteristic(Constants.DEX).getCharacteristicValue()),
                Math.round((float)hero.getCharacteristic(Constants.CON).getCharacteristicValue()),
                (int)Math.floor((float)hero.getCharacteristic(Constants.SPD).getCharacteristicValue()),
                Math.round((float)hero.getCharacteristic(Constants.REC).getCharacteristicValue()),
                Math.round((float)hero.getCharacteristic(Constants.EGO).getCharacteristicValue()),
                Math.round((float)hero.getCharacteristic(Constants.BODY).getSecondaryValue()),
                Math.round((float)hero.getCharacteristic(Constants.STUN).getSecondaryValue()),
                Math.round((float)hero.getCharacteristic(Constants.DEX).getSecondaryValue()),
                Math.round((float)hero.getCharacteristic(Constants.CON).getSecondaryValue()),
                (int)Math.floor((float)hero.getCharacteristic(Constants.SPD).getSecondaryValue()),
                Math.round((float)hero.getCharacteristic(Constants.REC).getSecondaryValue()),
                Math.round((float)hero.getCharacteristic(Constants.EGO).getSecondaryValue()));
    }
    /**
     * @param characterName
     * @param j 
     * @param i 
     * @param i 
     * @param d
     * @param e
     * @param f
     * @param g
     */
    public HeroPlaytimeRecord(String characterName, int bodyv, int stunv, int dexv, 
            int conv, int speedv, int recoveryv,int egov, int bodyv2, int stunv2, int dexv2, 
            int conv2, int speedv2, int recoveryv2,int egov2) {
        name = characterName;
        primaryBody = bodyv;
        primaryStun = stunv;       
        primaryDexterity = dexv;
        primaryConstitution = conv;
        primarySpeed = speedv;
        primaryRecovery = recoveryv;
        primaryEgo=egov;
        secondaryBody = bodyv2;
        secondaryStun = stunv2;       
        secondaryDexterity = dexv2;
        secondaryConstitution = conv2;
        secondarySpeed = speedv2;
        secondaryRecovery = recoveryv2;
        secondaryEgo=egov2;
        currentDexterity = dex();
        currentSpeed = speed();
       
        bodyTaken =0;
        stunTaken = 0;
        
    }
    
    public int speed() {
		if (useSecondarySPD)
			return secondarySpeed;
		else
			return primarySpeed;
	}
    
	public int dex() {
		if (useSecondaryDEX){
			return secondaryDexterity;
		} else{
			return primaryDexterity;
		}
	}
	
	public int ego() {
		if (useSecondaryEGO){
			return secondaryEgo;
		} else{
			return primaryEgo;
		}
	}
	
	public void topOfActingSegment(){
        damagedThisPhase = false;
    }
    
    public void endOfActingSegment(){
        // nothing right now
    }
    
    public void takeDamage(int stun, int body){
        stunTaken+=stun;
        bodyTaken+=body;
        if (stun > con()){
            stunned = true;
        } 
        if ((stun>0)||(body>0)){
            damagedThisPhase = true;
        }
        if (isUnconcious()){
        	stunned = false;
        }
        fireRecordChange();
    }
    
    private int con() {
		// TODO Auto-generated method stub
		return 0;
	}
	public int getStunTaken(){
        return stunTaken;
    }
    
    public int getBodyTaken(){
        return bodyTaken;
    }
    /* (non-Javadoc)
     * @see java.lang.Comparable#compareTo(java.lang.Object)
     */
    public int compareTo(Object o) {
        return name.compareTo(((HeroPlaytimeRecord)o).name);
    }
    /**
     * @param segment
     * @return
     */
    public boolean actsOnSegment(int segment) {
        return (heldAction || movesOn(segment));
    }
    /**
     * @param segment
     * @return
     */
    private boolean movesOn(int segment) {
        for(int i : speedChart[speed()]){
            if (i==segment){
                return true;
            }
        }
        return false;
    }
    
    public String toString(){
        return name;
    }
    /**
     * 
     */
    public void reset() {
        bodyTaken =0;
        stunTaken=0;
        fireRecordChange();
    }
    /**
     * @return
     */
    public boolean isDead() {        
        return bodyTaken>=body();
    }
    private int body() {
		if (useSecondaryBody){
			return secondaryBody;
		} else{
			return primaryBody;
		}
	}
	/**
     * @return
     */
    public boolean isUnconcious() {        
        return stunTaken>=stun();
    }
    
    public int stun() {
		if (useSecondaryStun){
			return secondaryStun;
		} else{
			return primaryStun;
		}
	}
	public boolean isStunned(){
        return stunned;
    }
    
    public void recoverFromStun(){
        stunned = false;
        fireRecordChange();
    }
    
    public boolean tookDamageThisSegment(){
        return damagedThisPhase;
    }
    /**
     * @return
     */
    public boolean canNeverAct() {
        // TODO put real code in to check for actors that are permenantly
        // out of it.
        return false;
    }
    /**
     * @param b
     */
    public void setStunned(boolean b) {
        stunned = b;
        fireRecordChange();
    }
    
    public void addListener(HeroPlaytimeRecordListener l){
    	listeners.add(l);
    }
    
    private void fireRecordChange(){
    	for(HeroPlaytimeRecordListener l : listeners){
    		l.recordChanged(this);
    	}
    }
	public void takeRecovery() {
		stunTaken -= recovery();
		if (stunTaken<0){
			stunTaken = 0;
		}
		fireRecordChange();
	}
	
	private int recovery() {
		if (useSecondaryREC){
			return secondaryRecovery;
		} else {
			return primaryRecovery;
		}
	}
	
	public boolean isUseSecondaryDEX() {
		return useSecondaryDEX;
	}
	public boolean isUseSecondarySPD() {
		return useSecondarySPD;
	}
	public boolean isUseSecondaryEGO() {
		return useSecondaryEGO;
	}
	public boolean isEGOBased() {
		return egoBased ;
	}
	public void setUseSecondaryDEX(boolean b) {
		useSecondaryDEX = b;
		
	}
	public void setUseSecondarySPD(boolean b) {
		useSecondarySPD = b;
		
	}
	public void setUseSecondaryEGO(boolean b) {
		useSecondaryEGO = b;
	}
	public void setEGOBased(boolean b) {
		egoBased = b;
		
	}
	public boolean isUseSecondaryBODY() {
		return useSecondaryBody;
	}
	public boolean isUseSecondarySTUN() {
		return useSecondaryStun;
	}
	public boolean isUseSecondaryREC() {
		return useSecondaryREC;
	}
	public void setUseSecondaryBODY(boolean b) {
		useSecondaryBody = b;
		
	}
	public void setUseSecondarySTUN(boolean b) {
		useSecondaryStun = b;
	}
	public void setUseSecondaryREC(boolean b) {
		useSecondaryREC = b;
		
	}
	public int getActingDex() {
		if (egoBased){
			return ego();
		} else {
			return dex();
		}
	}
}
